#!/usr/bin/env bash

. $(dirname $0)/util
set -eu -o pipefail

: ${TEST_INTEGRATION=}
: ${TEST_GATEWAY=}
: ${TEST_DOCKERFILE=}
: ${TEST_DOCKERD=}
: ${TEST_DOCKERD_BINARY=$(which dockerd)}
: ${TEST_COVERAGE=}
: ${TEST_KEEP_CACHE=}
: ${DOCKERFILE_RELEASES=}
: ${BUILDKIT_WORKER_RANDOM=}

if [ "$TEST_DOCKERD" == "1" ]; then
  if [ ! -f "$TEST_DOCKERD_BINARY" ]; then
    echo "dockerd binary not found"
    exit 1
  fi
  if [ ! -x "$TEST_DOCKERD_BINARY" ]; then
    chmod +x "$TEST_DOCKERD_BINARY"
  fi
  if ! file "$TEST_DOCKERD_BINARY" | grep "statically linked" >/dev/null; then
    echo "dockerd binary needs to be statically linked"
    exit 1
  fi
fi

if [ "$#" == 0 ]; then TEST_INTEGRATION=1; fi

while test $# -gt 0; do
  case "$1" in
    gateway)
      TEST_GATEWAY=1
      ;;
    dockerfile)
      TEST_DOCKERFILE=1
      ;;
    integration)
      TEST_INTEGRATION=1
      ;;
    *)
      echo "unknown arg $1"
      ;;
  esac
  shift
done

iid="buildkit-tests"
iidfile=$(mktemp -t docker-iidfile.XXXXXXXXXX)

coverageVol=""
coverageFlags=""
if [ "$TEST_COVERAGE" = "1" ]; then
  covdir="$(pwd)/coverage"
  mkdir -p "$covdir"
  coverageVol="-v $covdir:/coverage"
  coverageFlags="-coverprofile=/coverage/coverage.txt -covermode=atomic"
fi

buildxCmd build $cacheFromFlags \
  --target "integration-tests" \
  --output "type=docker,name=$iid" \
  $currentcontext

cacheVolume="buildkit-test-cache"
if ! docker container inspect "$cacheVolume" >/dev/null 2>/dev/null; then
  docker create -v /root/.cache -v /root/.cache/registry -v /go/pkg/mod --name "$cacheVolume" alpine
fi

if [ "$TEST_INTEGRATION" == 1 ]; then
  cid=$(docker create --rm -v /tmp $coverageVol --volumes-from=$cacheVolume -e TEST_DOCKERD -e SKIP_INTEGRATION_TESTS ${BUILDKIT_INTEGRATION_SNAPSHOTTER:+"-eBUILDKIT_INTEGRATION_SNAPSHOTTER"} -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry --privileged $iid go test $coverageFlags ${TESTFLAGS:--v} ${TESTPKGS:-./...})
  if [ "$TEST_DOCKERD" = "1" ]; then
    docker cp "$TEST_DOCKERD_BINARY" $cid:/usr/bin/dockerd
  fi
  docker start -a $cid
fi

if [ "$TEST_GATEWAY" == 1 ]; then
  # Build-test "github.com/moby/buildkit/frontend/gateway/client", which isn't otherwise built by CI
  # It really only needs buildkit-base. We have integration-tests in $iid, which is a direct child of buildkit-base.
  cid=$(docker create --rm --volumes-from=$cacheVolume $iid go build -v ./frontend/gateway/client)
  docker start -a $cid
fi

DOCKERFILE_RELEASES_CUSTOM=""
if [ "$TEST_DOCKERFILE" == 1 ]; then
  if [ -z $DOCKERFILE_RELEASES ]; then
    DOCKERFILE_RELEASES="mainline labs"
  else
    DOCKERFILE_RELEASES_CUSTOM=1
  fi

  # These tests run only on single random worker by default because the test matrix is big.
  # If flags are set then this is disabled and you need to use the flags to set specific worker.
  if [ -z "$BUILDKIT_WORKER_RANDOM" ] && [ -z "$TESTFLAGS" ]; then
    export BUILDKIT_WORKER_RANDOM=1
  fi

  for release in $DOCKERFILE_RELEASES; do
    buildtags=$(cat ./frontend/dockerfile/release/$release/tags)
    tarout=$(mktemp -t dockerfile-frontend.XXXXXXXXXX)

    buildxCmd build $cacheFromFlags \
      --build-arg "BUILDTAGS=$buildtags" \
      --file "./frontend/dockerfile/cmd/dockerfile-frontend/Dockerfile" \
      --output "type=oci,dest=$tarout" \
      $currentcontext

    if [ -s $tarout ]; then
      if [ "$release" = "mainline" ] || [ "$release" = "labs" ] || [ -n "$DOCKERFILE_RELEASES_CUSTOM" ] || [ "$GITHUB_ACTIONS" = "true" ]; then
        cid=$(docker create -v /tmp $coverageVol --rm --privileged --volumes-from=$cacheVolume -e TEST_DOCKERD -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry -e BUILDKIT_WORKER_RANDOM -e FRONTEND_GATEWAY_ONLY=local:/$release.tar -e EXTERNAL_DF_FRONTEND=/dockerfile-frontend $iid go test $coverageFlags --count=1 -tags "$buildtags" ${TESTFLAGS:--v} ./frontend/dockerfile)
        docker cp $tarout $cid:/$release.tar
        if [ "$TEST_DOCKERD" = "1" ]; then
          docker cp "$TEST_DOCKERD_BINARY" $cid:/usr/bin/dockerd
        fi
        docker start -a $cid
      fi
    fi
    rm $tarout
  done
fi

if [ "$TEST_KEEP_CACHE" != "1" ]; then
  docker rm -v $cacheVolume
fi
